package com.yixun.qfbao.api.service.impl;

import com.yixun.common.page.Page;
import com.yixun.common.page.PageUtil;
import com.yixun.qfbao.api.service.CustomerApiService;
import com.yixun.qfbao.apidto.GetCustomerPageReqDto;
import com.yixun.qfbao.common.model.PageDTO;
import com.yixun.qfbao.common.response.CommonResponse;
import com.yixun.qfbao.constant.StringConstant;
import com.yixun.qfbao.model.Customer;
import com.yixun.qfbao.model.dto.CustomerDto;
import com.yixun.qfbao.model.enums.DelFlagEnum;
import com.yixun.qfbao.model.initdto.InitCPCustomerDto;
import com.yixun.qfbao.service.CustomerService;
import com.yixun.qfbao.xf.model.CustomerPremises;
import com.yixun.qfbao.xf.model.Premises;
import com.yixun.qfbao.xf.model.dto.CustomerPremisesDto;
import com.yixun.qfbao.xf.model.dto.PremisesDto;
import com.yixun.qfbao.xf.model.enums.ResultEnum;
import com.yixun.qfbao.xf.service.CustomerPremisesService;
import com.yixun.qfbao.xf.service.PremisesService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CustomerApiServiceImpl implements CustomerApiService {

    @Autowired
    private CustomerService customerService;
    @Autowired
    private CustomerPremisesService customerPremisesService;
    @Autowired
    private PremisesService premisesService;

    @Override
    public void initCPCustomer(Date initStart, Date initEnd) {
        List<Customer> customerList = customerService.selectListByDto(new CustomerDto());
        Map<String, Long> customerMap = customerList.stream().collect(Collectors.toMap(item -> {
            Long agentId = item.getAgentId();
            String mobile = item.getMainMobile();
            Long originalReport = item.getOriginalReport();
            if(!mobile.contains(StringConstant.THREE_STAR)){
                return agentId + "-" + mobile;
            }else{
                return agentId + "-" + mobile + "-" + originalReport;
            }
        }, Customer::getId));
        CustomerPremisesDto cusPreDto = new CustomerPremisesDto();
        cusPreDto.setCreateTimeBefore(initStart);
        cusPreDto.setCreateTimeAfter(initEnd);
        List<InitCPCustomerDto> cpList = customerPremisesService.selectInitCPCustomerList(cusPreDto);
        // 报备Id、客户Id
        Map<Long, Long> updateCPMap = new HashMap<>();
        cpList.forEach(item -> {
            // 判断是否存在
            Customer customer = new Customer();
            String showKey = item.getStaffId() + "-" + item.getMobile();
            String hideKey = showKey + "-" + item.getId();
            if(Objects.nonNull(customerMap.get(showKey)) || Objects.nonNull(customerMap.get(hideKey))){
                updateCPMap.put(item.getId(), customerMap.get(showKey));
                if(item.getMobile().contains(StringConstant.THREE_STAR)){
                    updateCPMap.put(item.getId(), customerMap.get(hideKey));
                }
            }else {
                customer.setAgentCompany(item.getStaffCompanyId());
                customer.setAgentId(item.getStaffId());
                customer.setOriginalReport(item.getId());
                customer.setRealName(item.getName());
                customer.setGender(item.getGender());
                customer.setMainMobile(item.getMobile());
                customer.setDelFlag(DelFlagEnum.UNDEL.getNo());
                customer = customerService.create(customer);
                if(!item.getMobile().contains(StringConstant.THREE_STAR)){
                    customerMap.put(showKey, customer.getId());
                }else{
                    customerMap.put(hideKey, customer.getId());
                }
                updateCPMap.put(item.getId(), customer.getId());
            }
        });
        for(Map.Entry<Long, Long> entry: updateCPMap.entrySet()){
            Long cpId = entry.getKey();
            Long customerId = entry.getValue();
            CustomerPremisesDto cpDto = new CustomerPremisesDto();
            cpDto.setId(cpId);
            cpDto.setCustomerId(customerId);
            customerPremisesService.updateStatus(cpDto);
        }
    }

    @Override
    public void mergeAgentCustomer() {
        List<CustomerDto> repeatCustomerList = customerService.selectRepeatCustomerList();
        if(CollectionUtils.isNotEmpty(repeatCustomerList)){
            // 1、确定基础客户记录
            // 2、将所有报备绑定基础客户ID
            // 3、删除所有非基础客户的客户记录
            Long begin = System.currentTimeMillis();
            for(CustomerDto customerDto: repeatCustomerList){
                String customerIds = customerDto.getCustomerIds();
                if(StringUtils.isBlank(customerIds)){
                    continue;
                }
                String[] customerIdsArr = customerIds.split(",");
                String baseCustomerId = customerIdsArr[0];
                CustomerPremisesDto customerPremisesDto = new CustomerPremisesDto();
                customerPremisesDto.setCustomerId(Long.valueOf(baseCustomerId));
                customerPremisesDto.setCustomerIds(Arrays.asList(customerIdsArr));
                int updateCPCount = customerPremisesService.updateCustomerByCustomerIds(customerPremisesDto);
                log.info("update customer premises size: {}, update customers: {} to customer: {}", updateCPCount, customerIds, baseCustomerId);
                List<Long> removeCustomer = new ArrayList<>();
                for(String customerId: customerIdsArr){
                    if(StringUtils.isBlank(customerId) || StringUtils.equals(customerId, baseCustomerId)){
                       continue;
                    }
                    removeCustomer.add(Long.valueOf(customerId));
                }

                Customer customer = new Customer();
                customer.setDelFlag(DelFlagEnum.DEL.getNo());
                int removeCount = customerService.updateByIds(customer, removeCustomer);
                log.info("remove customer size: {}, remove ids: {}", removeCount, removeCustomer);
            }
            Long end = System.currentTimeMillis();
            log.info("used time: {}", end - begin);
        }
    }

    /**
     * 修改报备客户姓名、性别,同步修改关联报备的客户信息
     */
    @Override
    public void editCP2EditCustomer(Long reportId) {
        CustomerPremises customerPremises = customerPremisesService.selectById(reportId);
        if(Objects.isNull(customerPremises)){
            return;
        }
        Long customerId = customerPremises.getCustomerId();
        if(Objects.isNull(customerId)){
            return;
        }
        Customer customer = customerService.selectById(customerId);
        if(Objects.isNull(customer)){
            return;
        }
        // 报备Id和客户原始报备记录一致,更新客户信息
        if(customerPremises.getId().compareTo(customer.getOriginalReport()) == 0){
            CustomerDto customerDto = new CustomerDto();
            customerDto.setId(customer.getId());
            customerDto.setRealName(customerPremises.getName());
            customerDto.setGender(customerPremises.getGender());
            customerService.update(customerDto);
        }
    }

    /**
     * 修改客户信息
     * 同步修改客户关联的报备信息
     *
     */
    @Override
    public Boolean editCustomer2EditCP(Customer customer) {

        if(Objects.isNull(customer.getOriginalReport())){
            return Boolean.FALSE;
        }
        if(customer.getMainMobile().contains(StringConstant.THREE_STAR)){
            return Boolean.FALSE;
        }
        CustomerPremises customerPremises = customerPremisesService.selectById(customer.getOriginalReport());
        if(Objects.isNull(customerPremises)){
            return Boolean.FALSE;
        }
        CustomerPremisesDto cpDto = new CustomerPremisesDto();
        cpDto.setId(customerPremises.getId());
        cpDto.setName(customer.getRealName());
        cpDto.setMobile(customer.getMainMobile());
        cpDto.setGender(customer.getGender());
        cpDto.setCustomerId(customer.getId());
        customerPremisesService.updateStatus(cpDto);
        return Boolean.TRUE;
    }


    /**
     * 补全报备号码,变更客户信息
     */
    @Override
    public void completePhone2EditCustomer(Long reportId) {
        // 1、获取报备信息
        // 2、获取报备绑定的客户
        // 3、客户号码为全号
        // 3.1、判断补全后的号码与当前绑定号码是否一致
        // 3.1.1、一致: 客户不做变更,补全所有绑定此客户的报备记录号码
        // 3.1.2、不一致: 再判断经纪人名下是否存在相同号码的客户
        // 3.1.2.1、存在: 将报备记录关联到已存在的客户
        //               判断此客户下是否绑定有其他报备,没有其他报备可删除此客户
        // 3.1.2.2、不存在: 创建新客户并将报备绑定至新客户
        // 4、客户号码为隐号
        // 4.1、判断补全后号码是否存在
        // 4.1.1、存在: 将报备记录关联到已存在的客户
        //             判断此客户下是否绑定有其他报备,没有其他报备可删除此客户
        // 4.1.2、不存在: 补全客户号码
        //             同步补全所有绑定此隐号客户的报备
        CustomerPremises customerPremises = customerPremisesService.selectById(reportId);
        if(Objects.isNull(customerPremises)){
            return;
        }
        Long customerId = customerPremises.getCustomerId();
        if(Objects.isNull(customerId)){
            return;
        }
        Customer customer = customerService.selectById(customerId);
        if(Objects.isNull(customer)){
            return;
        }
        Long staffId = customerPremises.getStaffId();
        String reportMobile = customerPremises.getMobile();
        if(customer.getMainMobile().contains(StringConstant.THREE_STAR)){
            CustomerDto customerDto = new CustomerDto();
            customerDto.setAgentId(staffId);
            customerDto.setMainMobile(reportMobile);
            Customer completeCustomer = customerService.selectByDto(customerDto);
            if(Objects.isNull(completeCustomer)){
                // 补全此报备绑定的客户号码
                customerDto = new CustomerDto();
                customerDto.setId(customer.getId());
                customerDto.setMainMobile(reportMobile);
                customerService.update(customerDto);
                // 变更绑定此客户的所有报备中的号码
                CustomerPremisesDto customerPremisesDto = new CustomerPremisesDto();
                customerPremisesDto.setMobile(reportMobile);
                customerPremisesDto.setCustomerIds(Collections.singletonList(String.valueOf(customer.getId())));
                customerPremisesService.updateCustomerByCustomerIds(customerPremisesDto);
            }else{
                // 补全后号码存在,将存在的客户绑定到报备记录上
                CustomerPremisesDto cpDto = new CustomerPremisesDto();
                cpDto.setId(customerPremises.getId());
                cpDto.setCustomerId(completeCustomer.getId());
                customerPremisesService.updateStatus(cpDto);
                // 判断此客户下是否绑定有其他报备,没有其他报备可删除此客户
                cpDto = new CustomerPremisesDto();
                cpDto.setCustomerId(customerId);
                List<CustomerPremises> cusPreList = customerPremisesService.selectListByDto(cpDto);
                if(CollectionUtils.isEmpty(cusPreList)){
                    // 此客户名下已没有报备记录,删除此客户
                    customer.setDelFlag(DelFlagEnum.DEL.getNo());
                    customerService.update(customer);
                }
            }
        }else {
            if(StringUtils.equals(customerPremises.getMobile(), customer.getMainMobile())){
                CustomerPremisesDto customerPremisesDto = new CustomerPremisesDto();
                customerPremisesDto.setMobile(reportMobile);
                customerPremisesDto.setCustomerIds(Collections.singletonList(String.valueOf(customer.getId())));
                customerPremisesService.updateCustomerByCustomerIds(customerPremisesDto);
            }else{
                CustomerDto customerDto = new CustomerDto();
                customerDto.setAgentId(staffId);
                customerDto.setMainMobile(reportMobile);
                Customer completeCustomer = customerService.selectByDto(customerDto);
                if(Objects.isNull(completeCustomer)){
                    // 创建新客户
                    Customer addCustomer = new Customer();
                    addCustomer.setAgentCompany(customerPremises.getStaffCompanyId());
                    addCustomer.setAgentId(customerPremises.getStaffId());
                    addCustomer.setOriginalReport(customerPremises.getId());
                    addCustomer.setRealName(customerPremises.getName());
                    addCustomer.setGender(customerPremises.getGender());
                    addCustomer.setMainMobile(customerPremises.getMobile());
                    addCustomer.setDelFlag(DelFlagEnum.UNDEL.getNo());
                    addCustomer = customerService.create(addCustomer);
                    // 报备绑定至新客户
                    CustomerPremisesDto cpDto = new CustomerPremisesDto();
                    cpDto.setId(customerPremises.getId());
                    cpDto.setCustomerId(addCustomer.getId());
                    customerPremisesService.updateStatus(cpDto);
                }else{
                    // 补全后号码存在,将存在的客户绑定到报备记录上
                    CustomerPremisesDto cpDto = new CustomerPremisesDto();
                    cpDto.setId(customerPremises.getId());
                    cpDto.setCustomerId(completeCustomer.getId());
                    customerPremisesService.updateStatus(cpDto);
                    // 判断此客户下是否绑定有其他报备,没有其他报备可删除此客户
                    cpDto = new CustomerPremisesDto();
                    cpDto.setCustomerId(customerId);
                    List<CustomerPremises> cusPreList = customerPremisesService.selectListByDto(cpDto);
                    if(CollectionUtils.isEmpty(cusPreList)){
                        // 此客户名下已没有报备记录,删除此客户
                        customer.setDelFlag(DelFlagEnum.DEL.getNo());
                        customerService.update(customer);
                    }
                }
            }
        }
    }

    /**
     * 获取小程序客户分页
     */
    @Override
    public Page<Customer> getWeappCustomerPage(GetCustomerPageReqDto reqDto, PageDTO pageDTO) {
        CustomerDto customerDto = new CustomerDto();
        customerDto.setAgentId(reqDto.getUserId());
        customerDto.setSearchContent(reqDto.getSearchContent());
        customerDto.setOrders("t.create_time desc");
        int begin = PageUtil.begin(pageDTO.getPageNum(), pageDTO.getPageSize());
        int end = pageDTO.getPageSize();
        return customerService.getPageModel(customerDto, begin, end);
    }

    @Override
    public Customer getCustomerById(Long customerId) {
        return customerService.selectById(customerId);
    }

    @Override
    public CommonResponse saveOrEditCustomer(Customer customer) {
        CommonResponse response = new CommonResponse();
        response.setResponseCode(ResultEnum.SUCCESS.getNo());
        response.setResponseMessage(ResultEnum.SUCCESS.getDes());
        String mainMobile = customer.getMainMobile();
        // 优先校验是否存在
        CustomerDto exitDto = new CustomerDto();
        exitDto.setAgentId(customer.getAgentId());
        exitDto.setMainMobile(mainMobile);
        List<Customer> exitCustomerList = customerService.selectListByDto(exitDto);
        if(CollectionUtils.isNotEmpty(exitCustomerList)) {
            if(Objects.isNull(customer.getId())){
                // 新增客户时,发现经纪人名下存在此类客户.不做新增
                response.setResponseCode(ResultEnum.FAIL.getNo());
                response.setResponseMessage(ResultEnum.CUSTOMER_EXISTS.getDes());
                return response;
            }else{
                // 修改客户信息
                Customer updateCustomer = exitCustomerList.get(0);
                if(customer.getId().compareTo(updateCustomer.getId()) == 0){
                    BeanUtils.copyProperties(customer, updateCustomer);
                    customerService.saveOrUpdate(updateCustomer);
                }else{
                    response.setResponseCode(ResultEnum.FAIL.getNo());
                    response.setResponseMessage(ResultEnum.CUSTOMER_EXISTS.getDes());
                    return response;
                }
            }
        }else{
            // 不存在已有记录: 直接进行新增/修改操作
            customerService.saveOrUpdate(customer);
        }
        return response;
    }

    @Override
    public List<CustomerPremises> getCustomerHisReport(Long customerId) {
        if(Objects.isNull(customerId)){
            return null;
        }
        CustomerPremisesDto cpDto = new CustomerPremisesDto();
        cpDto.setCustomerId(customerId);
        List<CustomerPremises> cpList = customerPremisesService.selectListByDto(cpDto);
        List<Long> premisesIds = cpList.stream().map(CustomerPremises::getPremisesId)
                .collect(Collectors.toList());
        PremisesDto premisesDto = new PremisesDto();
        premisesDto.setPremisesIds(premisesIds);
        Map<Long, Premises> premisesMap = premisesService.selectSimpleListByDto(premisesDto)
                .stream().collect(Collectors.toMap(Premises::getId, Function.identity()));
        for (CustomerPremises item : cpList) {
            Premises premises = premisesMap.get(item.getPremisesId());
            if (Objects.nonNull(premises)) {
                item.setPremisesName(premises.getName());
            }
        }
        return cpList;
    }

    @Override
    public Map<String, String> getCustomerReportedPremises(List<String> customerIds, int limitSize) {
        Map<String, String> intentionPremisesMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(customerIds)){
            CustomerPremisesDto cpDto = new CustomerPremisesDto();
            cpDto.setCustomerIds(customerIds);
            cpDto.setOrders("create_time desc");
            List<CustomerPremises> cusPreList = customerPremisesService.selectListByDto(cpDto);
            List<Long> premisesIds = cusPreList.stream().map(CustomerPremises::getPremisesId)
                    .collect(Collectors.toList());
            PremisesDto premisesDto = new PremisesDto();
            premisesDto.setPremisesIds(premisesIds);
            List<Premises> premisesList = premisesService.selectSimpleListByDto(premisesDto);
            Map<Long, String> premisesMap = premisesList.stream()
                    .collect(Collectors.toMap(Premises::getId, Premises::getName));
            for (String customerId : customerIds) {
                StringBuilder premisesNames = new StringBuilder();
                int count = 0;
                List<Long> existsPremisesIds = new ArrayList<>();
                for (CustomerPremises customerPremises : cusPreList) {
                    String cusPreId = String.valueOf(customerPremises.getCustomerId());
                    if (customerId.equals(cusPreId)) {
                        Long premisesId = customerPremises.getPremisesId();
                        if (existsPremisesIds.contains(premisesId)) {
                            continue;
                        }
                        existsPremisesIds.add(premisesId);
                        if (count > limitSize) {
                            premisesNames = new StringBuilder(premisesNames.substring(0, premisesNames.length() - 1) + "...");
                            break;
                        } else {
                            premisesNames.append(premisesMap.get(premisesId)).append(",");
                        }
                        count++;
                    }
                }
                if (premisesNames.toString().endsWith(",")) {
                    premisesNames = new StringBuilder(premisesNames.substring(0, premisesNames.length() - 1));
                }
                intentionPremisesMap.put(customerId, premisesNames.toString());
            }
        }
        return intentionPremisesMap;
    }
}
